package ctrlMode

import (
	"emsctrl/db"
	"emsctrl/public"
	"emsctrl/util"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

var G_mng *Ctrl_Mode_Mng

type Ctrl_Mode_Mng struct {
	Yggl        float32
	Open        int
	RemoteTable *public.RemoteAdjCtrlRegTable
	CurrPolicy  *public.CurrentPolicy
}

func GetGridMeter_Power() (error, int) {
	var basics float64
	sprintf := fmt.Sprintf(`from(bucket:"%v")
	|> range(start: -%vs)
	|> filter(fn: (r) =>
	r._measurement == "gridmeter" and
	r._field == "%v"
	)
	|> mean()`, db.INFLUXDB_DATABASE, 5, "T12")
	err, i := db.WhereFind(sprintf, &basics)
	if err != nil {
		return err, i
	} else {
		fmt.Println("grid basiceval:", basics)
		return nil, i
	}
}

func GetBmsMeter_Power() (error, int) {
	var basics float64
	sprintf := fmt.Sprintf(`from(bucket:"%v")
	|> range(start: -%vs)
	|> filter(fn: (r) =>
	r._measurement == "bmsmeter" and
	r._field == "%v"
	)
	|> mean()`, db.INFLUXDB_DATABASE, 5, "T12")
	err, i := db.WhereFind(sprintf, &basics)
	if err != nil {
		return err, i
	} else {
		fmt.Println("bms basiceval:", basics)
		return nil, i
	}
}

func (cp *Ctrl_Mode_Mng) Run() {
	for {
		select {
		case data := <-cp.CurrPolicy.Cmd:
			fmt.Println("RUN:", data)
		case <-time.After(time.Second):
			if cp.CurrPolicy.RunModeSel != nil {
				cp.PolicyUpgrade(1)

				cp.TimeLineUpgrade()
				implement := cp.CurrPolicy.RunModeSel.Implement()
				if implement == false {
					cp.ForceToNullMode()
				}
			} else {

				fmt.Println("no run mode config !!!")
			}
			err, i := GetGridMeter_Power()

			if err != nil {
				fmt.Println(err) //没有发现数据
			} else if i == 0 {
				fmt.Println("grid data not find !!!!")
			}
			err, i2 := GetBmsMeter_Power()
			if err != nil {
				fmt.Println(err) //没有发现数据
			} else if i2 == 0 {
				fmt.Println("bms data not find !!!!")
			}

		}
	}
}

const (
	MANUAL_MODE = iota
	AUTO_MODE
	PROXY_SCHE
	MAINTEN_MODE
)
const (
	CONFIG_FILE = "/conf/polic.json"
)

func (Cp *Ctrl_Mode_Mng) ForceToNullMode() {
	Cp.CurrPolicy.RunModeSel = nil
	Cp.CurrPolicy.RemoteAdjRemoteCtrMng = public.RemoteAdjRemoteCtrlMng{}
}

func (Cp *Ctrl_Mode_Mng) RunModeSelect(Ra public.RemoteAdjRemoteCtrlMng, pri int) {
	if pri == 0 && Cp.CurrPolicy.RemoteAdjRemoteCtrMng.RemoteAdj.Priority < Ra.RemoteAdj.Priority {
		switch Ra.RemoteAdj.RunMode {
		case MANUAL_MODE:
			Cp.CurrPolicy.RunModeSel = &ManualPolicy{}
		case AUTO_MODE:
			Cp.CurrPolicy.RunModeSel = &AutoPolicy{}
		case PROXY_SCHE:
			Cp.CurrPolicy.RunModeSel = &Proxyschedue{}
		case MAINTEN_MODE:
			Cp.CurrPolicy.RunModeSel = &Maintenance{}
		}
		Cp.CurrPolicy.RemoteAdjRemoteCtrMng = Ra
		Cp.CurrPolicy.RunModeSel.PolicySet(Cp.CurrPolicy)
	} else if pri == 1 && Cp.CurrPolicy.RemoteAdjRemoteCtrMng.RemoteAdj.Priority <= Ra.RemoteAdj.Priority {
		switch Ra.RemoteAdj.RunMode {
		case MANUAL_MODE:
			Cp.CurrPolicy.RunModeSel = &ManualPolicy{}
		case AUTO_MODE:
			Cp.CurrPolicy.RunModeSel = &AutoPolicy{}
		case PROXY_SCHE:
			Cp.CurrPolicy.RunModeSel = &Proxyschedue{}
		case MAINTEN_MODE:
			Cp.CurrPolicy.RunModeSel = &Maintenance{}
		}
		Cp.CurrPolicy.RemoteAdjRemoteCtrMng = Ra
		Cp.CurrPolicy.RunModeSel.PolicySet(Cp.CurrPolicy)
	}
	Cp.CurrPolicy.PidInit()

}

func (cp *Ctrl_Mode_Mng) PolicyCfgInit() {

	for _, mng := range cp.RemoteTable.RemoteAdjCtrlTable {
		if mng.RemoteAdj.Date.StartDate == "" || mng.RemoteAdj.Date.EndDate == "" {
			cp.RunModeSelect(mng, 0)
		} else {
			interval := util.CompareDateInterval(mng.RemoteAdj.Date.EndDate, mng.RemoteAdj.Date.StartDate)
			if interval == true {
				if mng.RemoteAdj.Date.WeekDay == "" {
					cp.RunModeSelect(mng, 1)
				} else {
					index := strings.Index(mng.RemoteAdj.Date.WeekDay, strconv.Itoa(int(time.Now().Weekday())))
					if index != -1 {
						cp.RunModeSelect(mng, 1)
					}
				}
			}
		}
	}
}

func (cp *Ctrl_Mode_Mng) Api_Policy_Config(data []byte) {
	gtable := public.Get_Gtable()
	err := json.Unmarshal(data, &gtable)
	if err != nil {
		fmt.Println(err)
		return
	}
	cp.RemoteTable = &gtable
	cp.CurrPolicy.CurrTimeline.Index = 0
	cp.CurrPolicy.RemoteAdjRemoteCtrMng = public.RemoteAdjRemoteCtrlMng{}
	cp.TimeLineCalc()
	cp.PolicyCfgInit()
}

func PolicyInit() *Ctrl_Mode_Mng {
	G_mng := &Ctrl_Mode_Mng{}
	G_mng.Yggl = 100
	G_mng.Open = 1
	polic := public.Get_Current_Polic()
	gtable := public.Get_Gtable()
	G_mng.RemoteTable = &gtable
	G_mng.CurrPolicy = polic
	//dir, _ := os.Getwd()
	//open, err := os.Open(dir + CONFIG_FILE)
	//if err != nil {
	//	fmt.Println(err)
	//	return G_mng
	//}
	//buf, err := io.ReadAll(open)
	//err = json.Unmarshal(buf, &gtable)
	err := util.JsonReadFile(CONFIG_FILE, &gtable)
	if err != nil {
		fmt.Println(err)
	} else {
		G_mng.TimeLineCalc()
		G_mng.PolicyCfgInit()
	}
	//模拟数据
	G_mng.CurrPolicy.RemoteSignal.PcsFaultState = 0
	//mng.CurrPolicy.RemoteMetering.Soc = 10
	G_mng.CurrPolicy.RemoteMetering.ChargeStationPower = 20
	return G_mng
}

func (cp *Ctrl_Mode_Mng) TimeLineCalc() {
	for _, mng := range cp.RemoteTable.RemoteAdjCtrlTable {
		for i, line := range mng.RemoteAdj.TimeLine {
			if line.StartTime == "" || line.StopTime == "" {
				continue
			}
			split := strings.Split(line.StartTime, ":")
			h, _ := strconv.Atoi(split[0])
			m, _ := strconv.Atoi(split[1])
			s, _ := strconv.Atoi(split[2])
			mng.RemoteAdj.TimeLine[i].StartVal = util.GetSecond(h, m, s)
			split = strings.Split(line.StopTime, ":")
			h, _ = strconv.Atoi(split[0])
			m, _ = strconv.Atoi(split[1])
			s, _ = strconv.Atoi(split[2])
			mng.RemoteAdj.TimeLine[i].StopVal = util.GetSecond(h, m, s)
		}
	}
}

func (Cp *Ctrl_Mode_Mng) PolicyUpgrade(check int) {
	if check == 0 {
		Cp.PolicyCfgInit()
	} else {
		if util.CompareTimeSecond(900, 0) == true {
			if Cp.CurrPolicy.DayUpgrade == 0 {
				Cp.PolicyCfgInit()
				Cp.CurrPolicy.DayUpgrade = 1
			}
		} else {
			if Cp.CurrPolicy.DayUpgrade == 1 {
				Cp.CurrPolicy.DayUpgrade = 0
			}
		}
	}
}

func (Cp *Ctrl_Mode_Mng) TimeLineUpgrade() {
	if Cp.CurrPolicy.RemoteAdjRemoteCtrMng.RemoteAdj.RunMode == MANUAL_MODE {
		return
	}
	second := false
	for i, line := range Cp.CurrPolicy.RemoteAdjRemoteCtrMng.RemoteAdj.TimeLine {
		//fmt.Println(i, line.StartVal, line.StopVal)
		second = util.CompareTimeSecond(line.StopVal, line.StartVal)
		if second == true {
			//fmt.Println(line.Power, line.TrackPower, line.Ratio, line.Mode)
			if Cp.CurrPolicy.CurrTimeline.Index != i+1 {
				Cp.CurrPolicy.CurrTimeline = line
				Cp.CurrPolicy.CurrTimeline.Index = i + 1
			}
			break
		}
	}
	if second == false {
		Cp.CurrPolicy.CurrTimeline.Mode = public.CTRL_IDLE
	}
	fmt.Println("timeline:", second)
}
